package com.inspur.edp.team.service.impl;


import com.inspur.edp.common.CommonConstants;
import com.inspur.edp.common.CommonUtils;
import com.inspur.edp.common.ParamValidation;
import com.inspur.edp.common.cache.CacheKeyConstants;
import com.inspur.edp.common.cache.DistCacheHelper;
import com.inspur.edp.team.PaasTeamMemberService;
import com.inspur.edp.team.PaasTeamService;
import com.inspur.edp.team.converter.TeamConverter;
import com.inspur.edp.team.dao.PaasTeamDao;
import com.inspur.edp.team.domain.PaasTeam;
import com.inspur.edp.team.domain.PaasTeamMember;
import com.inspur.edp.team.dto.Team;
import com.inspur.edp.team.dto.TeamMember;
import com.inspur.edp.team.manager.PaasTeamManager;
import io.iec.edp.caf.boot.context.CAFContext;
import io.iec.edp.caf.commons.utils.SpringBeanUtils;
import io.iec.edp.caf.rpc.api.service.RpcClient;
import io.iec.edp.caf.sysmanager.api.data.user.User;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Sort;
import org.springframework.util.CollectionUtils;

import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.*;

/**
 * 团队定义服务实现类
 */
public class PaasTeamServiceImpl implements PaasTeamService {

    private PaasTeamDao paasTeamDao = SpringBeanUtils.getBean(PaasTeamDao.class);

    private PaasTeamManager paasTeamManager = SpringBeanUtils.getBean(PaasTeamManager.class);

    private PaasTeamMemberService paasTeamMemberService = SpringBeanUtils.getBean(PaasTeamMemberService.class);

    private TeamConverter teamConverter = SpringBeanUtils.getBean(TeamConverter.class);

    private RpcClient client = SpringBeanUtils.getBean(RpcClient.class);

    @Override
    public String addTeam(Team team) {
        try {
            // 参数校验
            if (Objects.isNull(team)) {
                throw new RuntimeException("param can't null");
            }
            ParamValidation.checkParam(team.getCode(), team.getName());

            // 团队code已存在，则不允许添加
            if (Objects.nonNull(getTeamByCode(team.getCode()))) {
                throw new RuntimeException("团队编号已存在,编号:" + team.getCode());
            }


            // 构造团队对象,并且构造团队成员对象，该创建者为开发团队中的一员
            User user = CommonUtils.findUserInfo();
            PaasTeam paasTeam = teamConverter.genPaasTeam(team, user);
            PaasTeamMember paasTeamMember = genPaasTeamMember(paasTeam, user);

            // 保存数据
            return paasTeamManager.saveTeamAndTeamMember(paasTeam, paasTeamMember);
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new RuntimeException("创建团队发生异常,团队对象：" + team.toString(), e);
        }
    }

    @Override
    public void updateTeam(Team team) {
        try {
            // 参数校验
            if (Objects.isNull(team)) {
                throw new RuntimeException("param can't null");
            }
            ParamValidation.checkParam(team.getId(), team.getCode(), team.getName());

            // 越权校验
            User user = CommonUtils.findUserInfo();
            paasTeamMemberService.accessPermissioncheck(user.getId(), user.getName(), team.getId());

            //团队校验
            PaasTeam paasTeam = getTeamById(team.getId());
            if (Objects.isNull(paasTeam)) {
                throw new RuntimeException("该团队已不存在");
            }

            // 管理员校验
            paasTeamMemberService.editRoleCheck(user.getId(),user.getName(),team.getId());

            // 团队code已存在，则不允许编辑
            PaasTeam tTeam = getTeamByCode(team.getCode());
            if (Objects.nonNull(tTeam) && !team.getId().equals(tTeam.getId())) {
                throw new RuntimeException("团队编号已存在,编号:" + team.getCode());
            }


            // 构造更新团队对象
            PaasTeam paasTeamForUpdate = paasTeam;
            constructPaasTeamForUpdate(paasTeamForUpdate, team, user);

            // 保存数据
            paasTeamDao.saveAndFlush(paasTeamForUpdate);

            // 移除缓存
            DistCacheHelper.getInstance().evict(CacheKeyConstants.LCM_CACHE_APAAS_ORGANIZATION + team.getId());
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new RuntimeException("更新团队发生异常,团队对象：" + team.toString(), e);
        }
    }

    @Override
    public List<Team> getTeam() {
        try {
            List<Team> result = new ArrayList<>();

            // 查询该用户有权查看的团队id
            String userId = CAFContext.current.getUserId();
            if (userId.equals("admin")) {
                return this.getAllTeam();
            }
                List<TeamMember> teamMemberList = paasTeamMemberService.getMemberByUserId(userId);
                Set<String> teamIdSets = new HashSet<>();
                if (!CollectionUtils.isEmpty(teamMemberList)) {
                    teamMemberList.forEach(teamMember1 -> teamIdSets.add(teamMember1.getTeamId()));
                }

                // 查询团队信息
                List<PaasTeam> paasTeamList = getTeamByIds(teamIdSets);

//            List<PaasProduct> paasProductList = productList.stream().sorted(Comparator.comparing(PaasProduct::getCreatedTime).reversed()).collect(Collectors.toList());

                // 转换为返回对象
                paasTeamList.forEach(paasTeam -> {
                    Team team = teamConverter.convert2Team(paasTeam);
                    result.add(team);
                });
            return result;
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new RuntimeException("获取团队列表发生异常", e);
        }
    }

    @Override
    public List<Team> getAllTeam() {
        try {
            List<Team> result = new ArrayList<>();


            // 查询团队信息
            List<PaasTeam> paasTeamList = paasTeamDao.findAll();

//            List<PaasProduct> paasProductList = productList.stream().sorted(Comparator.comparing(PaasProduct::getCreatedTime).reversed()).collect(Collectors.toList());

            // 转换为返回对象
            paasTeamList.forEach(paasTeam -> {
                Team team = teamConverter.convert2Team(paasTeam);
                result.add(team);
            });
            return result;
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new RuntimeException("获取所有团队列表发生异常", e);
        }
    }

    @Override
    public List<Team> getTeamByTeamId(List<String> teamIdList) {
        if (Objects.isNull(teamIdList)) {
            return null;
        }
        List<Team> teamList =new ArrayList<>();
        List<PaasTeam> paasTeamList = paasTeamDao.findAllById(teamIdList);
        if (!CollectionUtils.isEmpty(paasTeamList)) {
            for(PaasTeam paasTeam : paasTeamList){
                teamList.add(teamConverter.convert2Team(paasTeam));
            }
        }
        return teamList;
    }

    private PaasTeamMember genPaasTeamMember(PaasTeam paasTeam, User user) {
        PaasTeamMember paasTeamMember = new PaasTeamMember()
                .setId(UUID.randomUUID().toString())
                .setTeamId(paasTeam.getId())
                .setUserId(user.getId())
                .setRoleType(1)
                .setCreator(user.getName())
                .setCreatedTime(paasTeam.getCreatedTime())
                .setLastModifier(user.getName())
                .setLastModifiedTime(paasTeam.getLastModifiedTime())
                .setYn(CommonConstants.YN_YES);
        return paasTeamMember;
    }


    /**
     * 构造更新团队对象
     *
     * @param team
     * @param user
     * @return
     */
    private void constructPaasTeamForUpdate(PaasTeam paasTeam, Team team, User user) {
        paasTeam.setCode(team.getCode())
                .setName(team.getName())
                .setDescription(team.getDescription())
                .setLastModifier(user.getName())
                .setLastModifiedTime(Timestamp.valueOf(LocalDateTime.now()));
    }

    /**
     * 根据团队id查询团队信息
     *
     * @param teamId
     * @return
     */
    private PaasTeam getTeamById(String teamId) {
        if (Objects.isNull(teamId)) {
            return null;
        }
        PaasTeam paasTeam = null; // DistCacheHelper.getInstance().get(CacheKeyConstants.LCM_CACHE_APAAS_PRODUCT + productId, PaasProduct.class);
        if (Objects.nonNull(paasTeam)) {
            return paasTeam;
        }
        PaasTeam result = null;
        Optional<PaasTeam> teamOptional = paasTeamDao.findById(teamId);
        if (teamOptional.isPresent()) {
            result = teamOptional.get();
            DistCacheHelper.getInstance().put(CacheKeyConstants.LCM_CACHE_APAAS_ORGANIZATION + teamId, result);
        }
        return result;
    }

    /**
     * 根据团队id批量查询团队信息
     *
     * @param teamIdList
     * @return
     */
    private List<PaasTeam> getTeamByIds(Set<String> teamIdList) {
        return paasTeamDao.findByIdIn(teamIdList, Sort.by(Sort.Direction.DESC, "createdTime"));
    }

    /**
     * 根据团队code查询团队信息
     *
     * @param teamCode
     * @return
     */
    private PaasTeam getTeamByCode(String teamCode) {
        PaasTeam paasTeamQuery = new PaasTeam().setCode(teamCode).setYn(CommonConstants.YN_YES);
        Optional<PaasTeam> teamOptional = paasTeamDao.findOne(Example.of(paasTeamQuery));
        if (teamOptional.isPresent()) {
            return teamOptional.get();
        }
        return null;
    }

    /**
     * 根据团队名称查询团队信息
     *
     * @param teamName
     * @return
     */
    private PaasTeam getTeamByName(String teamName) {
        PaasTeam paasTeamQuery = new PaasTeam().setName(teamName).setYn(CommonConstants.YN_YES);
        List<PaasTeam> teamOptional = paasTeamDao.findAll(Example.of(paasTeamQuery));
        if (teamOptional != null && teamOptional.size()>0) {
            return teamOptional.get(0);
        }
        return null;
    }

    /**
     * 根据团队id查询团队信息
     *
     * @param teamId
     * @return
     */
    public Team getTeamByTeamId(String teamId) {
        if (Objects.isNull(teamId)) {
            return null;
        }
        PaasTeam result = null;
        Optional<PaasTeam> teamOptional = paasTeamDao.findById(teamId);
        if (teamOptional.isPresent()) {
            result = teamOptional.get();
            DistCacheHelper.getInstance().put(CacheKeyConstants.LCM_CACHE_APAAS_ORGANIZATION + teamId, result);
        }
        return teamConverter.convert2Team(result);
    }

}
